#ifndef _CHARDIVIDER_H
#define _CHARDIVIDER_H

#include "header.h"
#include "ml/Sample.h"

#include <vector>

using namespace std;

class CharExtracter {
public:
    /** change the grey source image "src" into binarized */
    static void binarize(uchar *dst, const uchar *src, int width, int height);
    
    /** return false is character image has more than one line characters or has none, else true */
    static bool divideChar(uchar *data, int iWidth, int iHeight, vector<uchar*> &picList, vector<int> &widthList, vector<int> &heightList);

    /** filter the noise in the picture. if strict, remove all likely noise */
    static void filterNoise(uchar *data, int width, int upside, int downside, bool strict = true);

private:
    static const float s_SCALETHRESHOLD;

    struct CRect {
        int x;
        int y;
        int width;
        int height;
        int rightSpace;
    } CRect;

    enum InputType {
        CHINESE = 10,
        ENGLISH,
        //STRICT,
        LOOSE
    };

    enum Scale {
        LEFT_TOOBIG = 100,
        LEFT_TOOSMALL,
        PROPER
    };

    CharExtracter(void) {
    };

    ~CharExtracter(void) {
    };

    /** to check whether the forground and the background color are assigned right */
    static bool check(const uchar *greyData, int width, int height);

    /** 
     * Remove the background in advance
     * @return false is character image has more than one line characters or has no one, else true 
     */
    static bool preProcess(const uchar *data, int iWidth, int iHeight, int *upside, int *downside);

    static bool horizontalRejectCalc(const uchar *data, int iWidth, int iHeight, int *upside, int *downside, int threshold);

    static bool removeBigConnected(uchar *newData, const uchar *data, int iWidth, int upside, int downside);

    /** According to the CharacterType, return TOOWIDTH if too wide, TOOHIGH if too high, APPROPRIATE if appropriate */
    static Scale scale(int width, int height, InputType type);

    /** Find the upside and downside of a character */
    static void findUpAndDown(const uchar *data, int iWidth, int *X, int *Y, int *cWidth, int *cHeight);

    /** 
     * According to the histgram, calculate the character width(cW) and the proper distance width(dW) 
     * @return false is character image has more than one line characters or has no one, else true
     */
    static bool divideHelp(const int *histagram, int iWidth, int *cW, int *dW, vector<int> *offList, vector<int> *cWlist, vector<int> *dWlist);

    static int calcMaxFreqValue(vector<int> *v);

    /** Check if it's a sign */
    static bool isSign(const uchar *data, int x, int y, int width, int height);

    static int findTroughFromSide(const int *histgram, int len);

    static void copyArea(uchar *dest, const uchar *src, int iWidth, int x, int y, int cW, int cH);

    static bool compare(const Sample *s1, const Sample *s2) {
        return s1->getClass() < s2->getClass();
    }

#ifdef _DEBUG
    static void DEBUG_markChar(uchar *data, int iWidth, int iHeight, int x, int y, int w, int h);
#endif

};

#endif
